package csel.view;


import java.awt.geom.AffineTransform;
import java.awt.image.*;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Graphics;
import java.awt.RenderingHints;

import csel.model.Direction;
import csel.model.GameObject;


/*
 * Reasons for Existence: Provides a visual representation and the functionality to display it. 
 * This allows separation of visual representation from the model's representation of an entity, 
 * item, &c. Provides the ability to draw an individual image to the screen, which allows greater 
 * flexibility in rendering the view.
 * 
 * @author Alex
 */

public class ObjectRepresentor {
	
	private BufferedImage img;
	private final GameObject myObject;
    private final int width;
    private final int height;
    private final int unitheight;
    private final AffineTransform tx = new AffineTransform();
    private Graphics2D gscale;
    
    
    /* drawing cache data */
    private Point cacheP;
    private Direction cacheD;
    
    public ObjectRepresentor(GameObject myObject)
    {
    	this.myObject = myObject;
    	if (myObject == null)
    	{
    		img = ImageRepository.getInstance().get("null");
    		width = img.getWidth();
    		height = img.getHeight();
    		unitheight = height/8;
    	}
    	else
    	{
    		img = ImageRepository.getInstance().get(myObject.getTypeId());
    		width = img.getWidth();
    		height = img.getHeight();
    		unitheight = height/8;
    	}
		tx.scale(3, 3);
		tx.translate(-180, -180);
    }
    
    protected int direction2Offset(Direction d)
    {
    	int startPoint;
    	
    	if (d == Direction.NORTH)
    		startPoint = 160;
    	else if (d == Direction.NORTHEAST)
    		startPoint = 200;
    	else if (d == Direction.EAST)
    		startPoint = 240;
    	else if (d == Direction.SOUTHEAST)
    		startPoint = 280;
    	else if (d == Direction.SOUTH)
    		startPoint = 0;
    	else if (d == Direction.SOUTHWEST)
    		startPoint = 40;
    	else if (d == Direction.WEST)
    		startPoint = 80;
    	else
    		startPoint = 120;
    	
    	return startPoint;
    }
    
    public void draw(Graphics g, Point p)
    {
    	gscale = (Graphics2D)g;
    	gscale.setTransform(tx);
		gscale.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		gscale.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    	//draws nothing if this representor's object is null
    	if (myObject == null)
    		return;
    	
    	//calculates what part of the sprite sheet to use based on direction
    	int startPoint = direction2Offset(myObject.getDirection());
    	int x = p.x;
    	int y = p.y;
   
    	//draws the image to the provided graphics
    	gscale.drawImage(img,
    		x, y, x + width, y + unitheight,
    		0, startPoint, 40, startPoint+40, null);
    }
    
    public void drawPrep(Point p)
    {
    	if (myObject == null)
    		return;
    	
    	cacheP = p;
    	cacheD = myObject.getDirection();
    }
    
    public void drawCached(Graphics g)
    {
    	gscale = (Graphics2D)g;
    	gscale.setTransform(tx);
		gscale.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		gscale.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    	if (myObject == null)
    		return;

    	//calculates what part of the sprite sheet to use based on direction
    	int startPoint = direction2Offset(cacheD);
    	int x = cacheP.x;
    	int y = cacheP.y;

    	gscale.drawImage(img,
				x, y, x + width, y + unitheight,
				0, startPoint, 40, startPoint+40, null);
    }
    
    public BufferedImage getSimpleImage()
    {
    	//returns the south-facing version of the sprite as an image
        return img.getSubimage(0,0,width,unitheight);
    }

}
